package com.acousticpayment.client.acoustic;

import java.io.InputStream;
import java.util.Timer;
import java.util.TimerTask;

import com.acousticpayment.client.acoustic.SessionService.SessionStatus;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.Button;

public class AcousticComm
{
	public static final int DATA_RECEIVED = 0xfffffff1;
	public boolean isReceiving = false;

	private Activity activity;
	private Handler handler;
	private Timer receiveListenerTimer;

	private SessionService mSessionService;
	private boolean mIsBound;

	private ServiceConnection mSessionConnection = new ServiceConnection()
	{
		public void onServiceConnected(ComponentName className, IBinder service)
		{
			// This is called when the connection with the service has been
			// established, giving us the service object we can use to
			// interact with the service. Because we have bound to a explicit
			// service that we know is running in our own process, we can
			// cast its IBinder to a concrete class and directly access it.
			mSessionService = ((SessionService.SessionBinder) service)
					.getService();
		}

		public void onServiceDisconnected(ComponentName className)
		{
			// This is called when the connection with the service has been
			// unexpectedly disconnected -- that is, its process crashed.
			// Because it is running in our same process, we should never
			// see this happen.
			mSessionService = null;
		}
	};

	void doBindService()
	{
		// Establish a connection with the service. We use an explicit
		// class name because we want a specific service implementation that
		// we know will be running in our own process (and thus won't be
		// supporting component replacement by other applications).
		activity.bindService(new Intent(activity, SessionService.class),
				mSessionConnection, Context.BIND_AUTO_CREATE);
		mIsBound = true;
	}

	void doUnbindService()
	{
		if (mIsBound)
		{
			// Detach our existing connection.
			activity.unbindService(mSessionConnection);
			mIsBound = false;
		}
	}

	Uri mCreateDataUri = null;
	String mCreateDataType = null;
	String mCreateDataExtraText = null;

	public AcousticComm(Activity activity)
	{
		this.activity = activity;
		// this.handler = handler;
		final Intent intent = activity.getIntent();
		final String action = intent.getAction();
		if (Intent.ACTION_SEND.equals(action))
		{
			mCreateDataUri = intent.getData();
			mCreateDataType = intent.getType();

			if (mCreateDataUri == null)
			{
				mCreateDataUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
			}

			mCreateDataExtraText = intent.getStringExtra(Intent.EXTRA_TEXT);

			if (mCreateDataUri == null)
				mCreateDataType = null;

			// The new entry was created, so assume all will end well and
			// set the result to be returned.
			activity.setResult(activity.RESULT_OK,
					(new Intent()).setAction(null));
		}
		doBindService();
	}

	private byte[] readDataFromUri(Uri uri)
	{
		byte[] buffer = null;

		try
		{
			InputStream stream = activity.getContentResolver().openInputStream(
					uri);

			int bytesAvailable = stream.available();
			// int maxBufferSize = 1024;
			int bufferSize = bytesAvailable; // Math.min(bytesAvailable,
												// maxBufferSize);
			int totalRead = 0;
			buffer = new byte[bufferSize];

			// read file and write it into form...
			int bytesRead = stream.read(buffer, 0, bufferSize);
			while (bytesRead > 0)
			{
				bytesRead = stream.read(buffer, totalRead, bufferSize);
				totalRead += bytesRead;
			}
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();

		}

		return buffer;
	}

	public void send(String str)
	{
		mSessionService.startSession(str);
	}

	public void receive(final Handler handler)
	{
		if (!isReceiving)
		{
			mSessionService.sessionReset();
			if (mSessionService.getStatus() == SessionStatus.NONE
					|| mSessionService.getStatus() == SessionStatus.FINISHED)
			{
				mSessionService.listen();
				// ((Button) v).setText("Stop listening");
			}
			else
			{
				mSessionService.stopListening();
				// ((Button) v).setText("Listen");
			}

			receiveListenerTimer = new Timer();
			receiveListenerTimer.schedule(new TimerTask()
			{
				@Override
				public void run()
				{
					if (!(mSessionService.getListenString().isEmpty()))
					{
						Message msg = new Message();
						msg.what = DATA_RECEIVED;
						Bundle bundle = new Bundle();
						// bundle.putSerializable("received_data",
						// data);//.putParcelableArray("test", data);
						// bundle.putByteArray("received_data", dataBytes);
						bundle.putCharSequence("received_data",
								mSessionService.getListenString());
						msg.setData(bundle);
						handler.sendMessage(msg);
						// reset the data received
						mSessionService.sessionReset();
					}
				}
			}, 500, 500);
			isReceiving = true;
		}
	}

	public void release()
	{
		if (receiveListenerTimer != null)
		{
			receiveListenerTimer.cancel();
			receiveListenerTimer = null;
		}
		mSessionService.stopListening();
		doUnbindService();
		isReceiving = false;
	}
}
